import { ChangeDetectorRef, DestroyRef, inject, Injectable } from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { finalize, map } from 'rxjs';

import { JsonPatchData } from '@app/core/domain/json-patch-data';
import { RequestParams } from '@app/core/domain/request-params';
import { BaseService } from '@app/core/services/http/base.service';
import { ModalBtnStatus } from '@app/widget/base-modal';
import { NzSafeAny } from 'ng-zorro-antd/core/types';
import { ModalOptions, NzModalService } from 'ng-zorro-antd/modal';
import { NzTableQueryParams } from 'ng-zorro-antd/table';

import { AntTableConfig, SortFile } from './ant-table.component';

export interface PageSearchParams {}

@Injectable({
  providedIn: 'root'
})
export class BaseTableComponent<TEntity> {
  isCollapse = true;
  pageSearchParam: Partial<PageSearchParams> = {};
  destroyRef = inject(DestroyRef);
  dataList: TEntity[] = [];
  modalService: NzSafeAny;
  dataService!: BaseService<TEntity>;
  tableConfig!: AntTableConfig;
  checkedCashArray: NzSafeAny[] = [];
  cdr: ChangeDetectorRef = inject(ChangeDetectorRef);
  nzModalService: NzModalService = inject(NzModalService);
  constructor() {}

  selectedChecked(e: NzSafeAny): void {
    this.checkedCashArray = [...e];
  }

  changePageSize(e: number): void {
    this.tableConfig.pageSize = e;
  }

  changeSort(e: SortFile): void {
    //e.fileName , e.sortDir
  }

  resetForm(): void {
    this.pageSearchParam = {};
    this.search();
  }

  toggleCollapse(): void {
    this.isCollapse = !this.isCollapse;
  }

  tableChangeDectction(): void {
    this.dataList = [...this.dataList];
    this.cdr.detectChanges();
  }

  tableLoading(isLoading: boolean): void {
    this.tableConfig.loading = isLoading;
    this.tableChangeDectction();
  }

  appendRequestParams(): RequestParams {
    const filter: Partial<TEntity> = {};
    let requestParams: RequestParams = {
      '@relationships': 'LoginInfo,Password',
      current: this.tableConfig.pageIndex,
      pageSize: this.tableConfig.pageSize,
      '@filter': '',
      ...filter
    };

    return requestParams;
  }

  search(): void {
    this.tableConfig.pageIndex = 1;
    this.loadDataList();
  }

  loadDataList(e?: NzTableQueryParams): void {
    if (e) {
      this.tableConfig.pageIndex = e?.pageIndex;
    }
    this.checkedCashArray = [...this.checkedCashArray];
    this.tableConfig.loading = true;
    let requestParams: RequestParams = this.appendRequestParams();

    this.dataService
      .getEntityPageList(requestParams)
      .pipe(
        finalize(() => {
          this.tableLoading(false);
        })
      )
      .subscribe(students => {
        const { records, total } = students;
        this.dataList = records;
        this.tableConfig.total = total;
      });
  }

  add(options: ModalOptions = { nzTitle: '新增' }): void {
    this.modalService
      .show(options)
      .pipe(
        finalize(() => {
          this.tableLoading(false);
        }),
        takeUntilDestroyed(this.destroyRef)
      )
      .subscribe((res: NzSafeAny) => {
        if (!res || res.status === ModalBtnStatus.Cancel) {
          return;
        }
        const param = { ...res.modalValue };
        this.tableLoading(true);
        this.addEditData(param, 'addEntity');
      });
  }

  edit(id: number, params?: TEntity | RequestParams, options: ModalOptions = { nzTitle: '编辑' }): void {
    this.dataService
      .getEntityById(id, params)
      .pipe(takeUntilDestroyed(this.destroyRef))
      .subscribe(res => {
        this.modalService
          .show(options, res[0])
          .pipe(
            finalize(() => {
              this.tableLoading(false);
            }),
            takeUntilDestroyed(this.destroyRef)
          )
          // @ts-ignore
          .subscribe(({ modalValue, status }) => {
            if (status === ModalBtnStatus.Cancel) {
              return;
            }
            modalValue.id = id;
            this.tableLoading(true);
            this.addEditData(modalValue, 'editEntity');
          });
      });
  }

  del(id: number, isLogicDel: boolean, fieldName: string = ''): void {
    const ids: number[] = [id];
    this.nzModalService.confirm({
      nzTitle: '确定要删除吗？',
      nzContent: '删除后不可恢复',
      nzOnOk: () => {
        this.tableLoading(true);
        if (isLogicDel) {
          const jsonPatchData: JsonPatchData = {
            id: id.toString(),
            op: 'Replace',
            path: fieldName,
            value: '1'
          };
          this.dataService.commonUpdate(id, [jsonPatchData]).subscribe(result => {
            this.loadDataList();
          });
        } else {
          this.dataService
            .delEntities(ids)
            .pipe(
              finalize(() => {
                this.tableLoading(false);
              }),
              takeUntilDestroyed(this.destroyRef)
            )
            .subscribe(() => {
              if (this.dataList.length === 1) {
                this.tableConfig.pageIndex--;
              }
              this.loadDataList();
            });
        }
      }
    });
  }

  addEditData(param: TEntity, methodName: 'editEntity' | 'addEntity'): void {
    this.dataService[methodName]([param])
      .pipe(
        finalize(() => {
          this.tableLoading(false);
        }),
        takeUntilDestroyed(this.destroyRef)
      )
      .subscribe(() => {
        this.loadDataList();
      });
  }
}
